﻿/*
 * KLF Headless Browser
 * Written by Kris Oye <kristianoye@gmail.com>
 * Copyright (C) 2011-2012.  All rights reserved.
 */
namespace KLF.Lib.Browser.DOM.CSS.SAC.Conditions
{
    #region Using Statements

    using System;
    using System.Linq;

    #endregion

    public class AttributeCondition : Condition
    {
        public AttributeCondition()
        {
            AttributeOperator = AttOp.HasAttribute;
        }

        public AttributeCondition(string name, string op, string val)
        {
            AttributeName = name;
            SetOperator(op);
            AttributeValue = val;
        }

        public AttributeCondition(string name, AttOp op, string val)
        {
            AttributeName = name;
            AttributeOperator = op;

            if (!String.IsNullOrEmpty(val))
            {
                if (val.StartsWith("\""))
                    val = val.Substring(1);
                if (val.EndsWith("\""))
                    val = val.Substring(0, val.Length - 1);
            }
            AttributeValue = val;
        }

        public string AttributeName
        {
            get
            {
                return StringLookup.GetValue(_attName);
            }
            set
            {
                _attName = new StringLookup(value);
            }
        }
        internal StringLookup _attName;

        public string AttributeValue
        {
            get
            {
                return StringLookup.GetValue(_attValue);
            }
            set
            {
                string val = value;
                if (val.StartsWith("\"") || val.StartsWith("'"))
                    val = val.Substring(1);
                if (val.EndsWith("\"") || val.EndsWith("'"))
                    val = val.Substring(0, val.Length - 1);
                _attValue = new StringLookup(val);
            }
        }
        internal StringLookup _attValue;

        public AttOp AttributeOperator { get; set; }

        public override bool MatchElement(KLF.Lib.Browser.DOM.HTML.HTMLElement e)
        {
            switch(AttributeOperator)
            {
                case AttOp.Contains:
                    return e.getAttribute(AttributeName).Contains(AttributeValue);

                case AttOp.EndsWith:
                    return e.getAttribute(AttributeName).EndsWith(AttributeValue);

                case AttOp.StartsWith:
                    return e.getAttribute(AttributeName).StartsWith(AttributeValue);

                case AttOp.HasAttribute:
                    return e.getAttribute(AttributeName).Length > 0;

                case AttOp.Equals:
                    return e.getAttribute(AttributeName).Equals(AttributeValue);

                case AttOp.ContainsS:
                    string[] listS = e.getAttribute(AttributeName).Split(' ');
                    return listS.Contains(AttributeValue);

                case AttOp.ContainsH:
                    string[] listH = e.getAttribute(AttributeName).Split(' ');
                    return listH.Contains(AttributeValue);
            }
            return false;
        }

        public override ConditionType Type
        {
            get
            {
                return ConditionType.AttributeCondition;
            }
        }

        internal void SetOperator(string p)
        {
            switch (p)
            {
                case "=": 
                    AttributeOperator = AttOp.Equals; 
                    break;

                case "|=": 
                    AttributeOperator = AttOp.ContainsH;
                    break;

                case "^=":
                    AttributeOperator = AttOp.StartsWith;
                    break;

                case "$=":
                    AttributeOperator = AttOp.EndsWith;
                    break;

                case "~=":
                    AttributeOperator = AttOp.ContainsS;
                    break;

                case "*=":
                    AttributeOperator = AttOp.Contains;
                    break;

                case "exists":
                    AttributeOperator = AttOp.HasAttribute;
                    break;
                default:
                    throw new ArgumentException("Attribute operator was invalid.");
            }
        }

        public static string OpToString(AttOp op)
        {
            switch(op)
            {
                case AttOp.Contains:
                    return "*=";
                case AttOp.EndsWith:
                    return "$=";
                case AttOp.StartsWith:
                    return "^=";
                case AttOp.ContainsH:
                    return "|=";
                case AttOp.ContainsS:
                    return "~=";
                case AttOp.Equals:
                    return "=";
                default:
                    return "??";
            }
        }

        public override string ToString()
        {
            if (AttributeOperator == AttOp.HasAttribute)
                return String.Format("[{0}]",
                    AttributeName);
            else
                return String.Format("[{0}{1}\"{2}\"]",
                    AttributeName,
                    OpToString(AttributeOperator), 
                    AttributeValue);
        }
    }
}
